<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'

interface Particle {
  x: number
  y: number
  vx: number
  vy: number
  size: number
  opacity: number
  color: string
}

const canvas = ref<HTMLCanvasElement>()
const particles = ref<Particle[]>([])

let ctx: CanvasRenderingContext2D | null = null
let animationId: number | null = null

/**
 * 初始化粒子系统
 */
const initParticles = () => {
  if (!canvas.value) return

  const rect = canvas.value.getBoundingClientRect()
  canvas.value.width = rect.width
  canvas.value.height = rect.height

  ctx = canvas.value.getContext('2d')
  if (!ctx) return

  particles.value = []
  const particleCount = Math.floor((rect.width * rect.height) / 15000)

  for (let i = 0; i < particleCount; i++) {
    particles.value.push(createParticle())
  }
}

/**
 * 创建单个粒子
 */
const createParticle = (): Particle => {
  const colors = ['#00ff88', '#00d4ff', '#8b5cf6', '#f472b6']

  return {
    x: Math.random() * (canvas.value?.width || 0),
    y: Math.random() * (canvas.value?.height || 0),
    vx: (Math.random() - 0.5) * 0.5,
    vy: (Math.random() - 0.5) * 0.5,
    size: Math.random() * 2 + 1,
    opacity: Math.random() * 0.5 + 0.1,
    color: colors[Math.floor(Math.random() * colors.length)]
  }
}

/**
 * 更新粒子位置
 */
const updateParticles = () => {
  if (!canvas.value) return

  particles.value.forEach(particle => {
    particle.x += particle.vx
    particle.y += particle.vy

    // 边界检测
    if (particle.x < 0 || particle.x > canvas.value!.width) {
      particle.vx *= -1
    }
    if (particle.y < 0 || particle.y > canvas.value!.height) {
      particle.vy *= -1
    }

    // 保持在画布内
    particle.x = Math.max(0, Math.min(canvas.value!.width, particle.x))
    particle.y = Math.max(0, Math.min(canvas.value!.height, particle.y))
  })
}

/**
 * 绘制粒子
 */
const drawParticles = () => {
  if (!ctx || !canvas.value) return

  ctx.clearRect(0, 0, canvas.value.width, canvas.value.height)

  particles.value.forEach(particle => {
    ctx!.save()
    ctx!.globalAlpha = particle.opacity
    ctx!.fillStyle = particle.color
    ctx!.beginPath()
    ctx!.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2)
    ctx!.fill()

    // 添加发光效果
    ctx!.shadowColor = particle.color
    ctx!.shadowBlur = particle.size * 2
    ctx!.fill()

    ctx!.restore()
  })

  // 绘制连接线
  drawConnections()
}

/**
 * 绘制粒子间的连接线
 */
const drawConnections = () => {
  if (!ctx) return

  const maxDistance = 100

  for (let i = 0; i < particles.value.length; i++) {
    for (let j = i + 1; j < particles.value.length; j++) {
      const dx = particles.value[i].x - particles.value[j].x
      const dy = particles.value[i].y - particles.value[j].y
      const distance = Math.sqrt(dx * dx + dy * dy)

      if (distance < maxDistance) {
        const opacity = (1 - distance / maxDistance) * 0.2

        ctx.save()
        ctx.globalAlpha = opacity
        ctx.strokeStyle = '#00ff88'
        ctx.lineWidth = 0.5
        ctx.beginPath()
        ctx.moveTo(particles.value[i].x, particles.value[i].y)
        ctx.lineTo(particles.value[j].x, particles.value[j].y)
        ctx.stroke()
        ctx.restore()
      }
    }
  }
}

/**
 * 动画循环
 */
const animate = () => {
  updateParticles()
  drawParticles()
  animationId = requestAnimationFrame(animate)
}

/**
 * 处理窗口大小变化
 */
const handleResize = () => {
  initParticles()
}

onMounted(() => {
  initParticles()
  animate()
  window.addEventListener('resize', handleResize)
})

onUnmounted(() => {
  if (animationId) {
    cancelAnimationFrame(animationId)
  }
  window.removeEventListener('resize', handleResize)
})
</script>

<template>
  <canvas
    ref="canvas"
    class="absolute inset-0 w-full h-full pointer-events-none"
    :style="{ zIndex: -1 }"
  />
</template>

<style scoped>
canvas {
  opacity: 0.6;
}
</style>
